import { EventEmitter } from 'events';
import redisClient from '../config/redis';
import { executionModel } from '../database/models';
import { ExecutionProgress } from './SQLExecutionEngine';

export interface ExecutionAlert {
  id: string;
  executionId: string;
  type: 'timeout' | 'error' | 'performance' | 'resource';
  severity: 'low' | 'medium' | 'high' | 'critical';
  message: string;
  timestamp: Date;
  resolved: boolean;
}

export interface PerformanceMetrics {
  executionId: string;
  cpuUsage?: number;
  memoryUsage?: number;
  diskIO?: number;
  networkIO?: number;
  queryComplexity?: number;
  estimatedCompletion?: Date;
}

export interface ExecutionSnapshot {
  executionId: string;
  status: string;
  progress: number;
  startTime: Date;
  currentDuration: number;
  estimatedTotalDuration?: number;
  currentStep?: string;
  performance?: PerformanceMetrics;
  alerts: ExecutionAlert[];
}

export class ExecutionMonitor extends EventEmitter {
  private static instance: ExecutionMonitor;
  private monitoringInterval: NodeJS.Timeout | null = null;
  private readonly MONITORING_INTERVAL = 5000; // 5秒
  private readonly ALERT_RETENTION_HOURS = 24;
  private readonly PERFORMANCE_HISTORY_HOURS = 1;

  private constructor() {
    super();
    this.startMonitoring();
  }

  public static getInstance(): ExecutionMonitor {
    if (!ExecutionMonitor.instance) {
      ExecutionMonitor.instance = new ExecutionMonitor();
    }
    return ExecutionMonitor.instance;
  }

  // 开始监控
  private startMonitoring(): void {
    this.monitoringInterval = setInterval(async () => {
      try {
        await this.performMonitoringCycle();
      } catch (error) {
        console.error('监控周期执行失败:', error);
      }
    }, this.MONITORING_INTERVAL);
  }

  // 执行监控周期
  private async performMonitoringCycle(): Promise<void> {
    // 获取所有运行中的执行
    const runningExecutions = await executionModel.getRunningExecutions();
    
    for (const execution of runningExecutions) {
      await this.monitorExecution(execution.id);
    }

    // 清理过期的监控数据
    await this.cleanupExpiredData();
  }

  // 监控单个执行
  private async monitorExecution(executionId: string): Promise<void> {
    try {
      const progress = await this.getExecutionProgress(executionId);
      if (!progress) return;

      const execution = await executionModel.findById(executionId);
      if (!execution) return;

      const currentTime = new Date();
      const startTime = execution.start_time;
      const currentDuration = currentTime.getTime() - startTime.getTime();

      // 检查超时
      await this.checkTimeout(executionId, currentDuration);

      // 检查性能问题
      await this.checkPerformanceIssues(executionId, currentDuration);

      // 更新执行快照
      await this.updateExecutionSnapshot(executionId, {
        executionId,
        status: execution.status,
        progress: progress.progress,
        startTime,
        currentDuration,
        currentStep: progress.currentStep,
        alerts: await this.getExecutionAlerts(executionId)
      });

      // 发出监控事件
      this.emit('executionMonitored', {
        executionId,
        status: execution.status,
        duration: currentDuration,
        progress: progress.progress
      });

    } catch (error) {
      console.error(`监控执行失败 ${executionId}:`, error);
    }
  }

  // 检查执行超时
  private async checkTimeout(executionId: string, currentDuration: number): Promise<void> {
    const DEFAULT_TIMEOUT = 300000; // 5分钟默认超时
    const WARNING_THRESHOLD = 0.8; // 80%时发出警告

    if (currentDuration > DEFAULT_TIMEOUT * WARNING_THRESHOLD) {
      await this.createAlert(executionId, {
        type: 'timeout',
        severity: currentDuration > DEFAULT_TIMEOUT ? 'critical' : 'medium',
        message: currentDuration > DEFAULT_TIMEOUT 
          ? `执行已超时 ${Math.round(currentDuration / 1000)}秒`
          : `执行即将超时，已运行 ${Math.round(currentDuration / 1000)}秒`
      });
    }
  }

  // 检查性能问题
  private async checkPerformanceIssues(executionId: string, currentDuration: number): Promise<void> {
    // 检查执行时间是否异常长
    const LONG_RUNNING_THRESHOLD = 120000; // 2分钟
    
    if (currentDuration > LONG_RUNNING_THRESHOLD) {
      await this.createAlert(executionId, {
        type: 'performance',
        severity: 'medium',
        message: `执行时间较长，已运行 ${Math.round(currentDuration / 1000)}秒`
      });
    }

    // 这里可以添加更多性能检查逻辑
    // 例如：内存使用、CPU使用、查询复杂度等
  }

  // 创建告警
  private async createAlert(executionId: string, alertData: {
    type: ExecutionAlert['type'];
    severity: ExecutionAlert['severity'];
    message: string;
  }): Promise<void> {
    const alertId = `alert_${executionId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    
    const alert: ExecutionAlert = {
      id: alertId,
      executionId,
      type: alertData.type,
      severity: alertData.severity,
      message: alertData.message,
      timestamp: new Date(),
      resolved: false
    };

    // 检查是否已存在相同类型的未解决告警
    const existingAlerts = await this.getExecutionAlerts(executionId);
    const duplicateAlert = existingAlerts.find(a => 
      a.type === alert.type && 
      !a.resolved && 
      a.message === alert.message
    );

    if (!duplicateAlert) {
      const alertKey = `execution:alerts:${executionId}`;
      await redisClient.hset(alertKey, alertId, JSON.stringify(alert));
      await redisClient.expire(alertKey, this.ALERT_RETENTION_HOURS * 3600);

      this.emit('alertCreated', alert);
    }
  }

  // 解决告警
  async resolveAlert(alertId: string): Promise<boolean> {
    try {
      // 查找告警
      const executionIds = await this.getAllMonitoredExecutions();
      
      for (const executionId of executionIds) {
        const alertKey = `execution:alerts:${executionId}`;
        const alertJson = await redisClient.hget(alertKey, alertId);
        
        if (alertJson) {
          const alert = JSON.parse(alertJson) as ExecutionAlert;
          alert.resolved = true;
          
          await redisClient.hset(alertKey, alertId, JSON.stringify(alert));
          
          this.emit('alertResolved', alert);
          return true;
        }
      }
      
      return false;
    } catch (error) {
      console.error(`解决告警失败 ${alertId}:`, error);
      return false;
    }
  }

  // 获取执行告警
  async getExecutionAlerts(executionId: string): Promise<ExecutionAlert[]> {
    try {
      const alertKey = `execution:alerts:${executionId}`;
      const alertsData = await redisClient.hgetall(alertKey);
      
      return Object.values(alertsData).map(alertJson => JSON.parse(alertJson));
    } catch (error) {
      console.error(`获取执行告警失败 ${executionId}:`, error);
      return [];
    }
  }

  // 获取所有告警
  async getAllAlerts(options: {
    severity?: ExecutionAlert['severity'];
    type?: ExecutionAlert['type'];
    resolved?: boolean;
    limit?: number;
  } = {}): Promise<ExecutionAlert[]> {
    try {
      const executionIds = await this.getAllMonitoredExecutions();
      const allAlerts: ExecutionAlert[] = [];

      for (const executionId of executionIds) {
        const alerts = await this.getExecutionAlerts(executionId);
        allAlerts.push(...alerts);
      }

      // 过滤告警
      let filteredAlerts = allAlerts;
      
      if (options.severity) {
        filteredAlerts = filteredAlerts.filter(a => a.severity === options.severity);
      }
      
      if (options.type) {
        filteredAlerts = filteredAlerts.filter(a => a.type === options.type);
      }
      
      if (options.resolved !== undefined) {
        filteredAlerts = filteredAlerts.filter(a => a.resolved === options.resolved);
      }

      // 按时间排序
      filteredAlerts.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());

      // 限制数量
      if (options.limit) {
        filteredAlerts = filteredAlerts.slice(0, options.limit);
      }

      return filteredAlerts;
    } catch (error) {
      console.error('获取所有告警失败:', error);
      return [];
    }
  }

  // 获取执行进度
  async getExecutionProgress(executionId: string): Promise<ExecutionProgress | null> {
    try {
      const progressKey = `execution:progress:${executionId}`;
      const progressData = await redisClient.get(progressKey);
      
      if (progressData) {
        return JSON.parse(progressData);
      }
      
      return null;
    } catch (error) {
      console.error(`获取执行进度失败 ${executionId}:`, error);
      return null;
    }
  }

  // 更新执行快照
  private async updateExecutionSnapshot(executionId: string, snapshot: ExecutionSnapshot): Promise<void> {
    try {
      const snapshotKey = `execution:snapshot:${executionId}`;
      await redisClient.setex(snapshotKey, 3600, JSON.stringify(snapshot)); // 1小时过期
    } catch (error) {
      console.error(`更新执行快照失败 ${executionId}:`, error);
    }
  }

  // 获取执行快照
  async getExecutionSnapshot(executionId: string): Promise<ExecutionSnapshot | null> {
    try {
      const snapshotKey = `execution:snapshot:${executionId}`;
      const snapshotData = await redisClient.get(snapshotKey);
      
      if (snapshotData) {
        return JSON.parse(snapshotData);
      }
      
      return null;
    } catch (error) {
      console.error(`获取执行快照失败 ${executionId}:`, error);
      return null;
    }
  }

  // 获取所有监控的执行
  private async getAllMonitoredExecutions(): Promise<string[]> {
    try {
      const pattern = 'execution:snapshot:*';
      const keys = await redisClient.keys(pattern);
      return keys.map(key => key.replace('execution:snapshot:', ''));
    } catch (error) {
      console.error('获取监控执行列表失败:', error);
      return [];
    }
  }

  // 记录性能指标
  async recordPerformanceMetrics(executionId: string, metrics: Partial<PerformanceMetrics>): Promise<void> {
    try {
      const metricsKey = `execution:performance:${executionId}`;
      const timestamp = Date.now();
      
      const performanceData = {
        ...metrics,
        executionId,
        timestamp
      };
      
      // 使用有序集合存储性能历史
      await redisClient.zadd(metricsKey, timestamp, JSON.stringify(performanceData));
      await redisClient.expire(metricsKey, this.PERFORMANCE_HISTORY_HOURS * 3600);
      
      this.emit('performanceRecorded', performanceData);
    } catch (error) {
      console.error(`记录性能指标失败 ${executionId}:`, error);
    }
  }

  // 获取性能历史
  async getPerformanceHistory(executionId: string, minutes: number = 60): Promise<PerformanceMetrics[]> {
    try {
      const metricsKey = `execution:performance:${executionId}`;
      const fromTime = Date.now() - (minutes * 60 * 1000);
      
      const metricsData = await redisClient.zrangebyscore(metricsKey, fromTime, '+inf');
      
      return metricsData.map(data => JSON.parse(data));
    } catch (error) {
      console.error(`获取性能历史失败 ${executionId}:`, error);
      return [];
    }
  }

  // 获取监控统计
  async getMonitoringStats(): Promise<{
    totalMonitoredExecutions: number;
    activeAlerts: number;
    criticalAlerts: number;
    avgExecutionTime: number;
    longestRunningExecution?: {
      executionId: string;
      duration: number;
    };
  }> {
    try {
      const executionIds = await this.getAllMonitoredExecutions();
      const allAlerts = await this.getAllAlerts({ resolved: false });
      const criticalAlerts = allAlerts.filter(a => a.severity === 'critical');

      let longestRunningExecution: { executionId: string; duration: number } | undefined;
      let totalDuration = 0;
      let executionCount = 0;

      for (const executionId of executionIds) {
        const snapshot = await this.getExecutionSnapshot(executionId);
        if (snapshot && snapshot.status === 'running') {
          executionCount++;
          totalDuration += snapshot.currentDuration;
          
          if (!longestRunningExecution || snapshot.currentDuration > longestRunningExecution.duration) {
            longestRunningExecution = {
              executionId,
              duration: snapshot.currentDuration
            };
          }
        }
      }

      return {
        totalMonitoredExecutions: executionIds.length,
        activeAlerts: allAlerts.length,
        criticalAlerts: criticalAlerts.length,
        avgExecutionTime: executionCount > 0 ? totalDuration / executionCount : 0,
        longestRunningExecution
      };
    } catch (error) {
      console.error('获取监控统计失败:', error);
      return {
        totalMonitoredExecutions: 0,
        activeAlerts: 0,
        criticalAlerts: 0,
        avgExecutionTime: 0
      };
    }
  }

  // 设置执行超时
  async setExecutionTimeout(executionId: string, timeoutMs: number): Promise<void> {
    try {
      const timeoutKey = `execution:timeout:${executionId}`;
      const timeoutData = {
        executionId,
        timeoutMs,
        setAt: new Date()
      };
      
      await redisClient.setex(timeoutKey, Math.ceil(timeoutMs / 1000), JSON.stringify(timeoutData));
      
      // 设置定时器检查超时
      setTimeout(async () => {
        const execution = await executionModel.findById(executionId);
        if (execution && execution.status === 'running') {
          await this.createAlert(executionId, {
            type: 'timeout',
            severity: 'critical',
            message: `执行超时 (${timeoutMs}ms)`
          });
        }
      }, timeoutMs);
      
    } catch (error) {
      console.error(`设置执行超时失败 ${executionId}:`, error);
    }
  }

  // 清理过期数据
  private async cleanupExpiredData(): Promise<void> {
    try {
      const cutoffTime = Date.now() - (this.ALERT_RETENTION_HOURS * 3600 * 1000);
      
      // 清理过期的告警
      const executionIds = await this.getAllMonitoredExecutions();
      for (const executionId of executionIds) {
        const alertKey = `execution:alerts:${executionId}`;
        const alerts = await redisClient.hgetall(alertKey);
        
        for (const [alertId, alertJson] of Object.entries(alerts)) {
          const alert = JSON.parse(alertJson) as ExecutionAlert;
          if (alert.timestamp.getTime() < cutoffTime) {
            await redisClient.hdel(alertKey, alertId);
          }
        }
      }
      
      // 清理过期的性能数据
      for (const executionId of executionIds) {
        const metricsKey = `execution:performance:${executionId}`;
        await redisClient.zremrangebyscore(metricsKey, '-inf', cutoffTime);
      }
      
    } catch (error) {
      console.error('清理过期数据失败:', error);
    }
  }

  // 停止监控
  stopMonitoring(): void {
    if (this.monitoringInterval) {
      clearInterval(this.monitoringInterval);
      this.monitoringInterval = null;
    }
    this.emit('monitoringStopped');
  }

  // 重启监控
  restartMonitoring(): void {
    this.stopMonitoring();
    this.startMonitoring();
    this.emit('monitoringRestarted');
  }

  // 获取监控健康状态
  async getMonitoringHealth(): Promise<{
    status: 'healthy' | 'warning' | 'critical';
    isRunning: boolean;
    lastCycleTime?: Date;
    issues: string[];
  }> {
    const stats = await this.getMonitoringStats();
    const issues: string[] = [];
    let status: 'healthy' | 'warning' | 'critical' = 'healthy';

    if (stats.criticalAlerts > 0) {
      issues.push(`${stats.criticalAlerts} 个严重告警`);
      status = 'critical';
    } else if (stats.activeAlerts > 5) {
      issues.push(`${stats.activeAlerts} 个活跃告警`);
      status = 'warning';
    }

    if (stats.longestRunningExecution && stats.longestRunningExecution.duration > 600000) {
      issues.push(`最长执行时间: ${Math.round(stats.longestRunningExecution.duration / 1000)}秒`);
      if (status === 'healthy') status = 'warning';
    }

    return {
      status,
      isRunning: this.monitoringInterval !== null,
      issues
    };
  }
}

// 导出单例实例
export const executionMonitor = ExecutionMonitor.getInstance();